//
// Created by hkkzzxz on 2025/1/9.
//

#include "UnderlyingClient.h"
#include <iostream>
#include <thread>

lrpc::UnderlyingClient::UnderlyingClient(boost::asio::io_context &ioContext, const std::string &host, int port)
        : socket_(ioContext), heartbeat_timer_(socket_.get_executor()) {
    tcp::resolver resolver(ioContext);
    resetHeartbeatTimer();
    auto endpoints = resolver.resolve(host, std::to_string(port));
    boost::asio::connect(socket_, endpoints);
}

lrpc::UnderlyingClient::~UnderlyingClient() {
    socket_.close();
    heartbeat_timer_.cancel();
}

void lrpc::UnderlyingClient::sendMessage(const std::vector<char> &message) {
    std::vector<char> bufferToSend;
    bufferToSend.push_back(false);
    uint32_t length = htonl(message.size());
    bufferToSend.insert(bufferToSend.end(), reinterpret_cast<char *>(&length),
                        reinterpret_cast<char *>(&length) + sizeof(length));
    bufferToSend.insert(bufferToSend.end(), message.begin(), message.end());
    boost::asio::co_spawn(socket_.get_executor(),
                          [this, bufferToSend]() -> boost::asio::awaitable<void> {
                              co_await send(bufferToSend);
                          },
                          boost::asio::detached);
}

std::vector<char> lrpc::UnderlyingClient::recvMessage() {
    std::promise<std::vector<char>> promise;
    auto future = promise.get_future();
    boost::asio::co_spawn(socket_.get_executor(),
                          [this, &promise]() -> boost::asio::awaitable<void> {
                              auto result = co_await recv();
                              promise.set_value(result);
                          },
                          boost::asio::detached);
    // 等待异步操作完成并返回结果
    return future.get();
}

boost::asio::awaitable<void> lrpc::UnderlyingClient::send(const std::vector<char> &message) {
    try {
        resetHeartbeatTimer();
        co_await boost::asio::async_write(socket_, boost::asio::buffer(message),
                                          boost::asio::use_awaitable);
    } catch (const boost::system::system_error &e) {

        socket_.close();
        heartbeat_timer_.cancel();
        co_return;
    }
}

boost::asio::awaitable<std::vector<char>> lrpc::UnderlyingClient::recv() {
    try {
        uint32_t length;
        // 读取响应长度
        co_await boost::asio::async_read(socket_, boost::asio::buffer(&length, sizeof(length)),
                                         boost::asio::use_awaitable);
        // 转换为主机字节序
        length = ntohl(length);
        std::vector<char> buffer(length);
        buffer.resize(length);
        // 读取响应内容
        co_await boost::asio::async_read(socket_, boost::asio::buffer(buffer, length), boost::asio::use_awaitable);
        std::string response(buffer.data(), length); // 创建响应字符串

        co_return buffer;
    } catch (const boost::system::system_error &e) {
        socket_.close();
        heartbeat_timer_.cancel();
        co_return std::vector<char>();
    }
}

void lrpc::UnderlyingClient::resetHeartbeatTimer() {
    // 心跳定时器设置为指定的时间间隔后过期
    heartbeat_timer_.expires_after(heartbeat_interval_);
    heartbeat_timer_.async_wait([this](boost::system::error_code ec) {
        if (!ec) {
            // 发送心跳包
            bool pd = true;
            // 使用co_spawn来启动一个新的协程，这样可以正确处理awaitable
            boost::asio::co_spawn(this->socket_.get_executor(),
                                  [this, pd]() -> boost::asio::awaitable<void> {
                                      try {
                                          co_await boost::asio::async_write(this->socket_,
                                                                            boost::asio::buffer(&pd, sizeof(bool)),
                                                                            boost::asio::use_awaitable);

                                      } catch (const boost::system::system_error &e) {

                                          this->socket_.close();
                                          this->heartbeat_timer_.cancel();
                                      }
                                      // 重置心跳定时器
                                      this->resetHeartbeatTimer();
                                  },
                                  boost::asio::detached);
        }
    });
}

void lrpc::UnderlyingClient::startUserInputLoop() {
    std::thread([this]() {
        while (true) {
            std::string userInput;
            std::getline(std::cin, userInput); // 读取用户输入

            if (userInput.empty()) {
                continue; // 忽略空输入
            }

            // 将用户输入转换为 std::vector<char>
            std::vector<char> message(userInput.begin(), userInput.end());

            // 发送消息
            this->sendMessage(message);

            // 接收服务器的响应
            auto response = this->recvMessage();
            if (!response.empty()) {
                std::string responseStr(response.begin(), response.end());
                std::cout << "Server response: " << responseStr << std::endl;
            }
        }
    }).detach(); // 分离线程，使其在后台运行
}